/**
  EG4Sim project, Anyang Normal University && IMP-CAS
  \class EG4NW
  \brief the model of Neotron Wall
  \author SUN Yazhou, asia.rabbit@163.com
  \since 2023-11-08
  \date 2023-11-08 last modified
  \copyright Copyright (c) 2023-2024 IMP-CAS with LGPLv3 LICENSE
*/

#include "EG4NW.h"
#include "G4Box.hh"
#include "G4NistManager.hh"
#include "G4LogicalVolume.hh"
#include "G4VisAttributes.hh"
#include "G4PVPlacement.hh"
#include "G4Colour.hh"
#include "G4SystemOfUnits.hh"
#include "G4VisAttributes.hh"

EG4NW::EG4NW() : EG4Det(), fSciStripLV(0), fFeStripLV(0), fSciLayerLV(0),
fFeLayerLV(0), fFe2LV(0), fFe4LV(0), fSci10LV(0), fFe2{0}, fFe4{0}, fSci10{0},
fSciStrip{0}, fFeStrip{0}, fSciLayer{0}, fFeLayer{0}, fVetoLV(0), fVetoStripLV(0),
fVeto(0), fVetoStrip{0}{
  // -- Material list -- //
  // plastic scintillators for NW (BC408)
  G4NistManager *nist = G4NistManager::Instance();
  auto sci = nist->FindOrBuildMaterial("G4_PLASTIC_SC_VINYLTOLUENE");
  auto Fe = nist->FindOrBuildMaterial("G4_Fe");
  G4Material *air = G4Material::GetMaterial("airLanzhou", true);

  auto grn = new G4VisAttributes(G4Colour(.8, .9, 1.)); // light green
  // construct a scintillator layer //
  fSciStripLV = new G4LogicalVolume(new G4Box("NWSciStrip", 720.*mm, 40.*mm, 40.*mm),
    sci, "NWSciStrip");
  fSciStripLV->SetVisAttributes(grn);
  // milky light green
  fSciLayerLV = new G4LogicalVolume(new G4Box("NWSciLayer", 720.*mm, 720.*mm, 40.*mm),
    air, "NWSciLayer");
  for(int i = 0; i < kNS; i++){
    char name[128]{}; sprintf(name, "NWSciStrip%d", i);
    fSciStrip[i] = new G4PVPlacement(nullptr,
      G4ThreeVector(0., (i-8-0.5)*80.*mm, 0.),
      fSciStripLV, name, fSciLayerLV, false, i, true);
  } // end for over scintillator strips

  // construct a Fe sandwich sampling layer //
  fFeStripLV = new G4LogicalVolume(
    new G4Box("NWFeStrip", 720.*mm, 40.*mm, 35.*mm), air, "NWFeStrip");
  fFe2LV = new G4LogicalVolume( // 2mm-thicnkness Fe
    new G4Box("NWFe2", 720.*mm, 40.*mm, 1.*mm), Fe, "NWFe2");
  fFe4LV = new G4LogicalVolume( // 4mm-thicnkness Fe
    new G4Box("NWFe4", 720.*mm, 40.*mm, 2.*mm), Fe, "NWFe4");
  fSci10LV = new G4LogicalVolume( // 10mm-thicnkness Sci
    new G4Box("NWSci10", 720.*mm, 40.*mm, 5.*mm), sci, "NWSci10");
  fSci10LV->SetVisAttributes(grn);
  // place the sub-strips - the iron strata
  fFe2[0] = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., 34.*mm),
    fFe2LV, "NWFe2_0", fFeStripLV, false, 0, true);
  fFe2[1] = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., -34.*mm),
    fFe2LV, "NWFe2_1", fFeStripLV, false, 1, true);
  for(int i = 0; i < 4; i++){
    char name[128]{}; sprintf(name, "NWFe4_%d", i);
    fFe4[i] = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., (-21.+i*14.)*mm),
      fFe4LV, name, fFeStripLV, false, i, true);
  } // end for over i
  // place the sub-strips - the sci strata
  for(int i = 0; i < 5; i++){
    char name[128]{}; sprintf(name, "NWSci10_%d", i);
    fSci10[i] = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., (-28.+i*14.)*mm),
      fSci10LV, name, fFeStripLV, false, i, true);
  } // end for over i
  fFeLayerLV = new G4LogicalVolume(
    new G4Box("NWFeLayer", 720.*mm, 720.*mm, 35.*mm), air, "NWFeLayer");
  // assembly the strips to a layer
  for(int i = 0; i < kNS; i++){
    char name[128]{}; sprintf(name, "NWFeStrip%d", i);
    fFeStrip[i] = new G4PVPlacement(nullptr,
      G4ThreeVector(0., (i-8-0.5)*80.*mm, 0.),
      fFeStripLV, name, fFeLayerLV, false, i, true);
  } // end for over scintillator strips

  // construct the whole NW
  fLV = new G4LogicalVolume(new G4Box("NW", 740.*mm, 770.*mm, 700.*mm),
    air, "NW");
  auto rot90 = new G4RotationMatrix(); rot90->rotateZ(90.*deg);
  // install the sci layers
  for(int i = 0; i < kNLS; i++){
    char name[128]{}; sprintf(name, "SciLayer%d", i);
    G4RotationMatrix *rot = i%2 ? rot90 : nullptr;
    fSciLayer[i] = new G4PVPlacement(rot, G4ThreeVector(0., 0., (i*80.-460.)*mm),
      fSciLayerLV, name, fLV, false, i, true);
  } // end for over
  // install the Fe layers
  for(int i = 0; i < kNLF; i++){
    char name[128]{}; sprintf(name, "FeLayer%d", i);
    G4RotationMatrix *rot = i%2 ? rot90 : nullptr;
    fFeLayer[i] = new G4PVPlacement(rot, G4ThreeVector(0., 0., (i*70.-305.)*mm),
      fFeLayerLV, name, fLV, false, i, true);
  } // end for over 

  // --------- the VETO TOFW --------- //
  fVetoLV = new G4LogicalVolume(new G4Box("NWVeto", 740.*mm, 770.*mm, 10.*mm),
    air, "NWVeto");
  // strips in VETO TOFWall
  fVetoStripLV = new G4LogicalVolume(new G4Box("NWVetoStrip", 740.*mm, 90.*mm, 5.*mm),
    sci, "NWVetoStrip");
  // milky light green
  fVetoStripLV->SetVisAttributes(grn);
  // assembly the veto strips
  for(int i = 0; i < kNSVETO; i++){
    char name[128]{}; sprintf(name, "NWVetoStrip%d", i);
    fVetoStrip[i] = new G4PVPlacement(nullptr,
      G4ThreeVector(0., (i-4)*170.*mm, i%2 ? -5.*mm : 5.*mm),
      fVetoStripLV, name, fVetoLV, false, i, true);
  } // end for over strips
  // place the veto TOFW
  fVeto = new G4PVPlacement(nullptr, G4ThreeVector(0., 0., -600.*mm),
    fVetoLV, "NWVeto", fLV, false, 0, true);
} // end ctor

EG4NW::~EG4NW(){}
